﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GTA
{
    public partial class FrmTaskDetails : BaseForm
    {
        #region Local Enumerations
        private enum NavigationDirection
        {
            First,
            Preview,
            Next,
            Last
        }
        #endregion

        #region Local Objects
        private List<BusinessEntity.Task> tasks;
        private Int32 currentIndex = 0;
        #endregion

        #region Starting Form
        public FrmTaskDetails()
        {
            InitializeComponent();
            currentIndex = 0;
        }
        public FrmTaskDetails(BusinessEntity.Task task)
            : this()
        {
            tasks = new List<GTA.BusinessEntity.Task>();
            tasks.Add(task);
        }
        public FrmTaskDetails(List<BusinessEntity.Task> tasks)
            : this()
        {
            this.tasks = tasks;
        }
        public FrmTaskDetails(List<BusinessEntity.Task> tasks, Int32 index)
            : this(tasks)
        {
            this.currentIndex = index;
            ShowCurrentIndex();
            if (!ValidateIndex(index))
                this.Close();
        }
        private void FormTaskDetails_Load(object sender, EventArgs e)
        {
            StartForm();
        }
        private void StartForm()
        {
            try
            {
                if (tasks != null && tasks.Count > 0)
                {
                    toolStripNavigation.Visible = tasks != null && tasks.Count > 1;
                    ShowCurrentIndex();
                    LoadStates();
                    LoadTaskDetails(tasks[currentIndex]);
                    lblQtdTasks.Text = tasks.Count.ToString();
                    LoadMenuTasksIDsNavigation();
                }
                else
                {
                    MessageBox.Show("Nenhuma task identificada", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.Close();
                }
            }
            catch (Exception ex)
            {
                HandleException("Inicialização da tela de detalhes da task.", ex);
            }
        }
        #endregion

        #region Events
        private void cmdFirst_Click(object sender, EventArgs e)
        {
            SetTaskPosition(NavigationDirection.First);
        }
        private void cmdPreview_Click(object sender, EventArgs e)
        {
            SetTaskPosition(NavigationDirection.Preview);
        }
        private void cmdNext_Click(object sender, EventArgs e)
        {
            SetTaskPosition(NavigationDirection.Next);
        }
        private void cmdLast_Click(object sender, EventArgs e)
        {
            SetTaskPosition(NavigationDirection.Last);
        }
        private void cmdFindTask_Click(object sender, EventArgs e)
        {
            FindTaskByIndex();
        }
        private void txtFilterTaskIndex_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (Convert.ToInt32(e.KeyChar) != (int)Keys.Back &&
                !Char.IsNumber(e.KeyChar))
                e.Handled = true;
        }
        private void txtFilterTaskID_Leave(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(txtFilterTaskIndex.Text))
            {
                for (Int32 i = 0; i < txtFilterTaskIndex.Text.Length; i++)
                {
                    if (!Char.IsNumber(txtFilterTaskIndex.Text, i))
                    {
                        MessageBox.Show("Valor Inválido!", "Alerta", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        txtFilterTaskIndex.Focus();
                        break;
                    }
                }
            }
        }
        private void mnTaskList_Click(object sender, EventArgs e)
        {
            mnTaskList.ShowDropDown();
        }
        private void cmdUpdate_Click(object sender, EventArgs e)
        {
            UpdateWorkItemData();
        }
        private void cmdImportTaskHistoryReport_Click(object sender, EventArgs e)
        {
            ImportTaskHistory();
        }
        private void dtRealizedStart_ValueChanged(object sender, EventArgs e)
        {
            CalculateRealizedHours(dtRealizedStart);
        }
        private void dtRealizedEnd_ValueChanged(object sender, EventArgs e)
        {
            CalculateRealizedHours(dtRealizedEnd);
        }
        #endregion

        #region Methods
        private void LoadStates()
        {
            try
            {
                BusinessLogic.GTA bl = new BusinessLogic.GTA();
                List<BusinessEntity.TaskDomain> states = bl.ListStates();
                cmbState.DisplayMember = "Description";
                cmbState.ValueMember = "ID";
                cmbState.DataSource = states;
            }
            catch (Exception ex)
            {
                HandleException("Carregar a lista de status", ex);
            }
        }
        private void LoadTaskDetails(BusinessEntity.Task task)
        {
            try
            {
                txtTaskID.Text = task.ID.ToString();
                txtAttemptionPoint.Text = task.AttemptionPoint != null ? task.AttemptionPoint.Description : String.Empty;
                txtCategory.Text = task.Category != null ? task.Category.Description : String.Empty;
                txtComplexity.Text = task.Complexity != null ? task.Complexity.Description : String.Empty;
                txtDescription.Text = task.Description.Replace("\n", "\r\n");
                txtDesignedTo.Text = task.DesignedTo != null ? task.DesignedTo.Name : String.Empty;
                txtIteration.Text = task.Iteration;
                txtModule.Text = task.Module;
                txtReason.Text = task.Reason;
                txtRealizedHours.Text = task.ScheduleRealizedHours != Int32.MinValue && task.ScheduleRealizedHours != 0 ? task.ScheduleRealizedHours.ToString() : String.Empty;
                txtScheduleEnd.Text = task.ScheduleEstimatedEnd != DateTime.MinValue ? task.ScheduleEstimatedEnd.ToString(DATE_FORMAT) : String.Empty;
                txtScheduleHours.Text = task.ScheduleEstimatedHours != Int32.MinValue ? task.ScheduleEstimatedHours.ToString() : String.Empty;
                txtScheduleStart.Text = task.ScheduleEstimatedStart != DateTime.MinValue ? task.ScheduleEstimatedStart.ToString(DATE_FORMAT) : String.Empty;
                txtTechnology.Text = task.Technology != null ? task.Technology.Description : String.Empty;
                txtTitle.Text = task.Title;

                dtRealizedStart.Checked = task.ScheduleRealizedStart != DateTime.MinValue;
                dtRealizedEnd.Checked = task.ScheduleRealizedEnd != DateTime.MinValue;
                if (dtRealizedStart.Checked)
                    dtRealizedStart.Value = task.ScheduleRealizedStart != DateTime.MinValue ? task.ScheduleRealizedStart : DateTime.Now;
                if (dtRealizedEnd.Checked)
                    dtRealizedEnd.Value = task.ScheduleRealizedEnd != DateTime.MinValue ? task.ScheduleRealizedEnd : DateTime.Now;

                if (task.State != null)
                    cmbState.SelectedValue = task.State.ID;
                else
                    cmbState.SelectedIndex = cmbState.Items.Count > 0 ? 0 : -1;
            }
            catch (Exception ex)
            {
                HandleException("Carregar os detalhes da task", ex);
            }
        }
        private void LoadMenuTasksIDsNavigation()
        {
            if (tasks != null && tasks.Count > 1)
            {
                foreach (BusinessEntity.Task itemTask in tasks)
                {
                    ToolStripItem toolItem = new ToolStripMenuItem(itemTask.ID.ToString() + " - " + itemTask.Title,
                                                                   null,
                                                                   new EventHandler(ToolItem_Click))
                                                                   {
                                                                       Tag = itemTask.ID
                                                                   };
                    mnTaskList.DropDownItems.Add(toolItem);
                }
            }
        }
        private void ToolItem_Click(Object sender, EventArgs e)
        {
            try
            {
                Int32 taskID = Convert.ToInt32(((ToolStripMenuItem)sender).Tag);
                currentIndex = tasks.FindIndex(t => t.ID.CompareTo(taskID) == 0);
                LoadTaskDetails(tasks[currentIndex]);
                ShowCurrentIndex();
            }
            catch (Exception ex)
            {
                HandleException("Localizar a Task pelo ID", ex);
            }
        }
        private void SetTaskPosition(NavigationDirection navigationDirection)
        {
            try
            {
                switch (navigationDirection)
                {
                    case NavigationDirection.First:
                        currentIndex = 0;
                        break;
                    case NavigationDirection.Preview:
                        if (currentIndex > 0)
                            currentIndex--;
                        break;
                    case NavigationDirection.Next:
                        if (currentIndex < tasks.Count - 1)
                            currentIndex++;
                        break;
                    case NavigationDirection.Last:
                        currentIndex = tasks.Count - 1;
                        break;
                }
                ShowCurrentIndex();
                LoadTaskDetails(tasks[currentIndex]);
            }
            catch (Exception ex)
            {
                HandleException("Definir a posição da task pela navegação", ex);
            }
        }
        private void ShowCurrentIndex()
        {
            lblCurrentIndex.Text = Convert.ToString(currentIndex + 1);
        }
        private void FindTaskByIndex()
        {
            if (!String.IsNullOrEmpty(txtFilterTaskIndex.Text))
            {
                Int32 idx = Convert.ToInt32(txtFilterTaskIndex.Text) - 1;
                if (ValidateIndex(idx))
                {
                    currentIndex = idx;
                    ShowCurrentIndex();
                    LoadTaskDetails(tasks[idx]);
                }
            }
        }
        private bool ValidateIndex(Int32 idx)
        {
            bool valid = true;
            if (idx < 0 || idx > tasks.Count - 1)
            {
                MessageBox.Show("Index inválido.\r\nInforme um index entre a quantidade de tasks existentes: [1] até [" + (tasks != null ? Convert.ToString(tasks.Count) : "1") + "]", "Alerta", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                valid = false;
            }
            return valid;
        }
        private void UpdateWorkItemData()
        {
            try
            {
                Cursor = Cursors.WaitCursor;
                BusinessEntity.Task task = GetTaskUpdated();
                new BusinessLogic.GTA().UpdateTaskData(task, Program.LoggedUser);
                MessageBox.Show("Dados salvos com sucesso!", "Confirmação", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                HandleException("Atualizar os dados do WorkItem no TeamSystem", ex);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
        private GTA.BusinessEntity.Task GetTaskUpdated()
        {
            tasks[currentIndex].ScheduleRealizedStart = dtRealizedStart.Checked ? dtRealizedStart.Value : DateTime.MinValue;
            tasks[currentIndex].ScheduleRealizedEnd = dtRealizedEnd.Checked ? dtRealizedEnd.Value : DateTime.MinValue;
            tasks[currentIndex].ScheduleRealizedHours = !String.IsNullOrEmpty(txtRealizedHours.Text.Trim()) ? Convert.ToInt32(txtRealizedHours.Text) : 0;
            tasks[currentIndex].State = cmbState.SelectedItem as BusinessEntity.TaskDomain;
            tasks[currentIndex].History = txtHistory.Text;
            return tasks[currentIndex];
        }
        private void ImportTaskHistory()
        {
            try
            {
                BusinessLogic.GTA bl = new BusinessLogic.GTA();
                List<BusinessEntity.TaskHistory> history = bl.ListTaskHistory(Program.LoggedUser, tasks[currentIndex]);
                if (history != null && history.Count > 0)
                {
                    if (MessageBox.Show("Deseja realmente importar o relatório de histórico de interrupções para o WorkItem? \r\nEsta ação automaticamente registrará uma entrada no histórico do WorkItem com o conteúdo do relatório.\r\n\r\nContinuar?", "Questão", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        tasks[currentIndex].History = bl.GetTaskHistoryHTMLFormat(history);
                        bl.UpdateTaskData(tasks[currentIndex], Program.LoggedUser);
                        MessageBox.Show("Histórico de Interrupções importado com sucesso!", "Confirmação", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                else
                    MessageBox.Show("Não existe histórico de interrupção registrado para esta tarefa!", "Alerta", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                HandleException("Importar o relatório de histórico de interrupções da task.", ex);
            }
        }
        private void CalculateRealizedHours(DateTimePicker dt)
        {
            try
            {
                if (dtRealizedStart.Checked &&
                    dtRealizedEnd.Checked)
                {
                    if (dtRealizedEnd.Value > dtRealizedStart.Value)
                    {
                        Int32 qtdDays = dtRealizedEnd.Value.Subtract(dtRealizedStart.Value).Days;
                        Int32 validDays = 0;

                        for (Int32 i = 0; i < qtdDays; i++)
                        {
                            bool shouldCount = true;

                            if (dtRealizedStart.Value.AddDays(i).DayOfWeek == DayOfWeek.Saturday ||
                                dtRealizedStart.Value.AddDays(i).DayOfWeek == DayOfWeek.Sunday)
                                shouldCount = false;

                            if (Program.Holidays != null &&
                                Program.Holidays.Holiday != null &&
                                Program.Holidays.Holiday.Count > 0 &&
                                Program.Holidays.Holiday.Exists(it => it.Date.CompareTo(dtRealizedStart.Value.AddDays(i).Date) == 0))
                                shouldCount = false;

                            if (tasks[currentIndex].DesignedTo.UserAbsences != null &&
                                tasks[currentIndex].DesignedTo.UserAbsences.Count > 0 &&
                                tasks[currentIndex].DesignedTo.UserAbsences.Exists(it => dtRealizedStart.Value.AddDays(i).Date.CompareTo(it.StartDate.Date) >= 0 &&
                                                                            dtRealizedStart.Value.AddDays(i).Date.CompareTo(it.EndDate.Date) <= 0))
                                shouldCount = false;

                            if (!shouldCount &&
                                tasks[currentIndex].DesignedTo.UserAdditionalDays != null &&
                                tasks[currentIndex].DesignedTo.UserAdditionalDays.Count > 0 &&
                                tasks[currentIndex].DesignedTo.UserAdditionalDays.Exists(it => it.Date.CompareTo(dtRealizedStart.Value.AddDays(i).Date) == 0))
                                shouldCount = true;

                            if (shouldCount)
                                validDays++;
                        }

                        Int32 totalHours = validDays * 8;
                        txtRealizedHours.Text = totalHours.ToString();
                    }
                    else
                        txtRealizedHours.Text = String.Empty;
                }
                else
                    txtRealizedHours.Text = String.Empty;
            }
            catch (Exception ex)
            {
                HandleException("Calcular as horas realizadas", ex);
            }
        }
        #endregion
    }
}
